import { _renderFont } from './shapes/fontClass'
import { _renderRect } from './shapes/rectClass'

async function drawBase(ctx: any, shape: any) {
  if (shape.type == 'Rect') {
    await drawRect(ctx, shape)
  } else if (shape.type == 'Font') {
    await drawFont(ctx, shape)
  }
}

/**
 * 返回内部模式和外部模式border的形状和canvas默认居中border形状，需要绘制长、宽的倍数
 */
async function drawRect(ctx: any, shape: any) {
  let { scaleW, scaleH } = scaleStrokeFun(shape)
  ctx.save()
  ctx.save()
  ctx.translate(shape.x + 0.5 * shape.width, shape.y + 0.5 * shape.height)
  ctx.scale(scaleW, scaleH)
  _renderRect(ctx, shape)
  // 为了生成不变形的阴影
  ctx.fill()
  ctx.restore()
  ctx.translate(shape.x, shape.y)
  await _renderFillStyle(ctx, shape)
  ctx.fill()
  if (shape.stroke.lineWidth != 0) {
    _renderLine(ctx, shape.stroke)
    await _renderStrokeStyle(ctx, shape)
    ctx.stroke()
  }
  ctx.restore()
}
async function drawFont(ctx: any, shape: any) {
  ctx.save()
  ctx.translate(shape.x, shape.y)
  await _renderFillStyle(ctx, shape)
  _renderLine(ctx, shape.stroke)
  await _renderStrokeStyle(ctx, shape)
  _renderFont(ctx, shape)
  ctx.restore()
}
/**
 * 返回内部模式和外部模式border的形状和canvas默认居中border形状，需要绘制长、宽的倍数
 */
function scaleStrokeFun(shape: any) {
  let data = {
    scaleW: 1,
    scaleH: 1,
  }
  if (shape.stroke.mode == 'inside') {
    let width = shape.width - shape.stroke.lineWidth
    let height = shape.height - shape.stroke.lineWidth
    data.scaleW = width / shape.width
    data.scaleH = height / shape.height
  } else if (shape.stroke.mode == 'outside') {
    let width = shape.width + shape.stroke.lineWidth,
      height = shape.height + shape.stroke.lineWidth
    data.scaleW = width / shape.width
    data.scaleH = height / shape.height
  }

  return data
}

async function _renderFillStyle(ctx: any, shape: any) {
  ctx.fillStyle = await _renderFill(ctx, shape.fill, shape)
}
async function _renderStrokeStyle(ctx: any, shape: any) {
  ctx.strokeStyle = await _renderFill(ctx, shape.stroke, shape)
}

/**
 * 绘制线段或border的模式、宽度等配置
 */
function _renderLine(ctx: any, line: any) {
  ctx.setLineDash([])
  ctx.lineDashOffset = 0
  ctx.lineWidth = line.lineWidth
  ctx.lineCap = 'round'
}

/**
 * 返回填充颜色、渐变、图片等填充样式
 */
async function _renderFill(ctx: any, fill: any, shape: any) {
  let style: any
  if (fill.type == 'color') {
    style = fill.color
  }
  if (fill.type == 'radialGradient') {
    // 环形渐变
    style = ctx.createRadialGradient(
      fill.gradient.x0 - shape.x,
      fill.gradient.y0 - shape.y,
      fill.gradient.r0,
      fill.gradient.x1 - shape.x,
      fill.gradient.y1 - shape.y,
      fill.gradient.r1
    )
  }

  if (fill.type == 'linearGradient') {
    // 线形渐变
    style = ctx.createLinearGradient(
      fill.gradient.x0 - shape.x,
      fill.gradient.y0 - shape.y,
      fill.gradient.x1 - shape.x,
      fill.gradient.y1 - shape.y
    )
  }

  if (['linearGradient', 'radialGradient'].includes(fill.type)) {
    fill.gradualColor.forEach((item: any) => {
      style.addColorStop(item.step * 0.01, item.color)
    })
  }

  if (fill.type == 'Img') {
    let img = await getImage(fill.url, fill.width, fill.height)
    let image = imageChangeSize(img, fill.width, fill.height)
    if (fill.imgMode.includes('repeat')) {
      style = ctx.createPattern(image, fill.imgMode)
    } else {
      style = ctx.createPattern(image, 'no-repeat')
    }
  }
  return style
}

/**
 * 修改了图片的尺寸用来填充图形
 */
function imageChangeSize(img: any, width: number, height: number) {
  let canvas = document.createElement('canvas')
  canvas.width = width
  canvas.height = height
  let ctx = canvas.getContext('2d') as CanvasRenderingContext2D
  ctx.drawImage(img, 0, 0, width, height)
  return canvas
}

/**
 * 获取图片完成加载后的实例对象
 */
export function getImage(imageData: any, width: number, height: number) {
  return new Promise((resolve, reject) => {
    let img = new Image(width, height)
    img.src = imageData
    img.crossOrigin = 'anonymous'
    img.onload = function () {
      console.log(img.width, img.height, 'img sc')
      resolve(img)
    }
  })
}
export {
  drawBase,
  drawRect,
  drawFont,
  scaleStrokeFun,
  _renderFillStyle,
  _renderStrokeStyle,
  _renderLine,
  _renderFill,
}
